﻿using Microsoft.AspNetCore.Mvc;
using MVC_Demo.Models.Database;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MVC_Demo.Controllers
{
    /// <summary>
    /// Test控制器 TestController类 继承控制器基类
    /// </summary>
    /// 仅对该控制器 执行该规则的路由 特性路由(属性路由)优先级 比 常规路由高
    //[Route("[controller]/[action]")]
    //[Route("/hwh/[controller]/[action]")]

    //特性路由 仅在这个控制器生效 并且 会让常规路由失效
    [Route("api/[controller]/[action]")]
    [Route("[controller]/[action]")]
    public class TestController : Controller
    {
        //私有的  只读的   数据库上下文类    对象
        private readonly Store_2022Context _db;

        //第二种方法 依赖注入
        /// <summary>
        /// TestController类的构造方法 类在实例化的时候 首先调用的方法
        /// 初始化操作 数据上下文 对象 数据操作 （增删改查）
        /// </summary>
        /// <param name="_db"></param>
        public TestController(Store_2022Context db)
        {
            //赋值
            _db = db;
        }

        public IActionResult AddTEST()
        {
            //1、new一个分类对象
            var cate = new Category()
            {
                CateName = "苹果15ProMax"
            };

            //2、数据添加
            //数据库上下文.表名[分类表].Add[操作(增删改查)](对象【分类数据】)
            _db.Categories.Add(cate);

            //3、保存 执行SQL
            //  数据库上下文.保存方法();
            //  判断执行 是成功还是失败
            var row = _db.SaveChanges();
            //return View();
            //      返回一个内容 文本
            return Content("添加数据");
        }

        //在Test控制器添加AddRange方法(添加多条数据方法)
        public IActionResult AddRange()
        {
            //new 一个对象列表
            var list = new List<Category>();
            list.Add(new Category
            {
                CateName = "家具"
            });
            list.Add(new Category
            {
                CateName = "家电"
            });
            list.Add(new Category
            {
                CateName = "苹果15ProMax"
            });
            //2、数据添加
            //数据库上下文.表名[分类表].Add[操作(增删改查)](对象【分类数据】)
            _db.Categories.AddRange(list);

            //3、保存 执行SQL
            //  数据库上下文.保存方法();
            //  判断执行 是成功还是失败
            var row = _db.SaveChanges();
            //如果影响行数
            if (row > 0)
                return Content("添加数据成功");
            else
                return Content("添加数据失败");
        }

        public IActionResult AddGoods()
        {
            //新增一个商品数据
            //new一个商品对象 等同于数据
            var good = new Good()
            {
                Name = "苹果15ProMax",
                CateId = 1,
                //互联网系统 图片用链接表示 "http：//boy.com/img.jpg"
                Cover = "",
                Price = 10000,
                Stock = 100,
                CreateTime = DateTime.Now,
            };

            //2、数据添加
            //数据库上下文.表名[分类表].Add[操作(增删改查)](对象【分类数据】)
            _db.Goods.Add(good);

            //3、保存 执行SQL
            //  数据库上下文.保存方法();
            //  判断执行 是成功还是失败
            var row = _db.SaveChanges();
            //如果影响行数
            if (row > 0)
                return Content("添加数据成功");
            else
                return Content("添加数据失败");
        }
        /// <summary>
        /// Index方法
        /// </summary>
        /// <returns></returns>
        /// 仅对该控制器 执行该规则的路由 特性路由(属性路由)优先级 比 常规路由高
        /*[Route("/")]*/
        /* [Route("/index")]
         [Route("/home")]*/
        public IActionResult Index()
        {
            //返回了View()方法
            //作用 调用Veiw方法 实际上 帮我们找到这个视图（页面）
            //找页面的规则 默认Views文件夹/Test(控制器)/Index(视图名)
            //不默认
            //return View("/home/myview");
            return View();
        }

        /// <summary>
        /// 查询数据列表
        /// </summary>
        /// <returns></returns>
        public IActionResult GetList()
        {
            //查询所有数据
            //        数据库上下文.表名.操作方法
            var list = _db.Categories.ToList();
            //条件查询数据列表  x为变量 分类变量
            //        数据库上下文.表名.where[查询条件](具体条件【判断】).ToList()【基础前面的条件查询数据】执行SQL
            var lists = _db.Categories.Where(x => x.CateName == "手机").ToString();
            //条件查询单条数据      FirstOrDefault:当数据不存在时返回值null
            //_db.Categories.First()  当数据不存在时候 会报错
            var data = _db.Categories.FirstOrDefault(x => x.Id == 1);
            return new ObjectResult(list);
        }

        //在Test控制器添加GetGoods方法，查询分类Id为1的所有商品数据
        /// <summary>
        /// 查询商品数据
        /// </summary>
        /// <returns></returns>
        public IActionResult GetGoods()
        {
            //查询分类ID为1的所有商品数据
            //数据库上下文.表名.操作方法
            var list = _db.Goods.Where(x => x.CateId == 1).ToString();
            return new ObjectResult(list);
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <returns></returns>
        public IActionResult Update()
        {
            //SQL update Category set CateName="手机111" where Id=1

            //查询Id为110的数据          null
            var model = _db.Categories.FirstOrDefault(x => x.Id == 112);

            //如果没有数据 返回提示“数据不存在”
            if (model == null)
            {
                //做出合理的错误处理
                return Content("数据不存在");
            }

            //赋值 null.CateName
            model.CateName = "手机123";

            //更新
            //数据库上下文.表名.操作
            _db.Categories.Update(model);

            //保存    执行SQL
            var row = _db.SaveChanges();

            //如果影响行数>0
            if (row > 0)
            {
                return Content("添加成功！");
            }
            else
                return Content("添加失败！");
        }

        /// <summary>
        /// 更新多条数据
        /// </summary>
        /// <returns></returns>
        public IActionResult UpdateRange()
        {
            //                       like '%手机%'  =  字符串Contains 包含某个字符串   
            var list = _db.Categories.Where(x => x.CateName.Contains("手机")).ToList();
            //遍历循环 对某个List进行循环遍历  逐个元素循环
            // foreach(var[声明变量] item[遍历元素的变量名] in list【列表对象】 )
            foreach (var item in list)
            {
                //赋值
                item.CateName = item.CateName + "(更新)";
            }

            //更新
            _db.Categories.UpdateRange(list);

            //保存 执行SQL
            var row = _db.SaveChanges();
            //如果影响行数>0
            if (row > 0)
            {
                return Content("添加成功！");
            }
            else
                return Content("添加失败！");
        }

        //在Test控制器添加UpdateGoods方法，1新增的数据分类Id为2
        public IActionResult UpdateGoods()
        {
            //把Id=65商品 更新为分类Id==1
            var model = _db.Goods.FirstOrDefault(x => x.Id == 65);

            if (model == null)
            {
                return Content("商品不存在");
            }
            //赋值
            model.CateId = 2;
            model.Name = "new_Name新名字";

            //更新操作
            _db.Goods.Update(model);
            var row = _db.SaveChanges();
            if (row > 0)
            {
                return Content("成功");
            }
            return Content("失败");
        }
        /// <summary>
        /// 删除数据
        /// </summary>
        /// <returns></returns>
        public IActionResult Remove()
        {
            //查询Id为1的数据
            var model = _db.Categories.FirstOrDefault(x => x.Id == 1);

            //如果没有数据 返回提示
            if (model == null)
            {
                return Content("数据不存在");
            }

            //删除
            _db.Categories.Remove(model);

            //保存 执行SQL
            var row = _db.SaveChanges();

            //如果影响行数>0
            if (row > 0)
                return Content("删除成功");
            return Content("删除失败");
        }

        public IActionResult RemoveRange()
        {
            //把包含“家”的分类查出来
            var list = _db.Categories.Where(x => x.CateName.Contains("家")).ToList();

            //删除
            _db.Categories.RemoveRange(list);

            //保存 执行SQL
            var row = _db.SaveChanges();

            //如果影响行数>0
            if (row > 0)
                return Content("删除成功");
            return Content("删除失败");
        }
        public IActionResult OrderBy()
        {
            //查询一个商品分类           列表 
            var list = _db.Categories.ToList();
            //条件查询                       条件(lamda表达式 结果)
            var list1 = _db.Categories.Where(x => x.CateName == "家具").ToList();
            var list2 = _db.Categories.Where(x => x.CateName == "家具").Where(x => x.Id > 0).ToList();
            //链式
            //排序                     排序lamda表达式  select * from category order by id 正序的排序
            var list3 = _db.Categories.OrderBy(x => x.Id).ToList();
            //排序                     排序lamda表达式  select * from category order by id desc 倒序的排序
            var list4 = _db.Categories.OrderByDescending(x => x.Id).ToList();
            //第一排序分类名称 第二排序是Id                       混合排序
            var list5 = _db.Categories.OrderByDescending(x => x.CateName).ThenBy(x => x.Id).ToList();
            return new ObjectResult(list);
        }
        public IActionResult SoftGoods()
        {
            //查询商品数据且   分类ID(CateId)    倒序显示
            var list6 = _db.Goods.OrderByDescending(x => x.CateId).ToList();
            return new ObjectResult(list6);
        }
        public IActionResult SkipAndTake()
        {
            //分类列表 126~131
            var list = _db.Categories.OrderBy(x => x.Id).ToList();
            //只要后面4个 一共6个 =》 跳过前面2个 取后面的。
            //跳过skip() 只管跳过 使用这个方法前 必须要有一个排序规则
            var list1 = _db.Categories.OrderBy(x => x.Id).Skip(2).ToList();
            //取前N个数据Take 只要前面4个
            var list2 = _db.Categories.OrderBy(x => x.Id).Take(4).ToList();
            //2~4个 126（不要） 127 128 129 
            var list3 = _db.Categories.OrderBy(x => x.Id).Skip(1).Take(3).ToList();
            //3~6
            var list4 = _db.Categories.OrderBy(x => x.Id).Skip(2).Take(4).ToList();

            //              10                      61
            //分页 一页数量PageSize 数据库总共的数量Total 算出页数
            //60/ 10  6
            //页数 ：total/pagesize+1
            //查询分类分页 1页2个 查询第二页 第一页跳过2
            var list5 = _db.Categories.OrderBy(x => x.Id).Skip(2).Take(2).ToList();

            //126
            //127

            //128
            //129

            //130
            //131
            //                                     pageIndex=1 skip=0
            //                                     pageIndex=2 skip=2
            //                                     pageIndex=3 skip=4
            //                                     pageIndex=x skip=（x-1）*pageSize

            //126
            //127
            //128

            //129
            //130
            //131
            //                                     pageIndex=1 skip=0   (1-1)*3  
            //                                     pageIndex=2 skip=3  (2-1)*3
            //                                     pageIndex=x skip=（x-1）*pageSize
            //每页数量
            int pageSize = 4;
            //页码
            int pageIndex = 2;

            var list6 = _db.Categories.OrderBy(x => x.Id)
                .Skip((pageIndex - 1) * pageSize)
                .Take(pageSize)  //一页的数量
                .ToList();

            return new ObjectResult(list);
        }
        //在Test控制器添加SkipGoods方法，查询以商品金额倒序的3-7个商品
        public IActionResult SkipGoods()
        {
            var list7 = _db.Goods.OrderByDescending(x => x.Price).Skip(2).Take(5).ToList();
            return new ObjectResult(list7);
        }

        //判断数据是否存在方法
        public IActionResult Any()
        {
            //判断列表有没有数据  有ture 没有就是false
            var result = _db.Categories.Any();
            //根据条件判断列表有没有数据 判断有没有 数据分类名称 == "家电"
            var result1 = _db.Categories.Where(x => x.CateName == "家电").Any();
            //等同于
            var result2 = _db.Categories.Any(x => x.CateName == "家电");
            return Content("");
        }

        //在Test控制器添加AnyGoods方法，判断商品金额为100的商品是否存在
        public IActionResult AnyGoods()
        {
            //   Goods  Price=100      Any()方法
            //判断商品 金额为100 的商品 是否存在
            //var result = _db.Goods.Where(x => x.Price == 100).Any();
            //等价于
            var result = _db.Goods.Any(x => x.Price == 100);
            //如果存在返回“存在”否则返回“不存在”
            if (result)
                return Content("存在");
            /*else
                return Content("不存在");*/
            return Content("");
        }
        public IActionResult Count()
        {
            //分类表数据总量
            var count = _db.Categories.Count();

            //待条件
            var count1 = _db.Categories.Count(x => x.CateName.Contains("家"));

            return new ObjectResult(count1);
        }

        public IActionResult Sum()
        {
            //商品金额进行求和 商品表的所有数据
            var sum1 = _db.Goods.Sum(x => x.Price);
            //根据条件求和
            var sum2 = _db.Goods.Where(x => x.CateId == 1).Sum(x => x.Price);

            //平均数
            var avg = _db.Goods.Average(x => x.Price);
            return new ObjectResult(sum1);
        }

        //在Test控制器添加CountGoods方法，查询商品金额为500-1000的商品数量
        public IActionResult CountGoods()
        {
            //查询商品金额为500-1000的商品数量
            var result = _db.Goods.Count(x => x.Price >= 500 && x.Price <= 1000);
            return new ObjectResult(result);
        }
        //在Test控制器添加SumGoods方法，查询分类Id为“1”的商品总额
        public IActionResult SumGoods()
        {
            //查询分类Id为“1”的商品总额
            //条件：分类ID（CateId=1） 
            var total = _db.Goods.Where(x => x.CateId == 1).Sum(x => x.Price);
            return new ObjectResult(total);
        }
        public IActionResult Grouby()
        {
            //sql select CateId
            //查询某一分类分组数据
            //统计每一个分类的 商品数量\商品总额
            //        对一个字段进行分组    构造一个查询结果
            var list = _db.Goods.GroupBy(x => x.CateId).Select(x => new
            {
                //自己组装这个查询结果
                x.Key, //分组的字段CateId
                Count = x.Count(),
                //        对金额求和
                Sum = x.Sum(z => z.Price),
                Avg = x.Average(z => z.Price),
                //获取求和统计count  sum  avg
            }).ToList();
            return new ObjectResult(list);
        }

        //在Test控制器添加StockGoods方法，统计每个分类的总库存
        public IActionResult StockGoods()
        {
            //统计每个分类的总库存
            var list = _db.Goods.GroupBy(x => x.CateId).Select(x => new
            {
                x.Key,//分组字段
                Stock = x.Sum(z => z.Stock)
            }).ToList();
            return new ObjectResult(list);
        }
        //       4
        //select Goods.Id, Goods.Name, Category.CateName from Goods
        //            1                2              3
        //inner join Category on  Goods.CateId = Category.Id

        public IActionResult Join()
        {
            //商品表  //1、要连接的表 2、需要连接的表    3、被连接的表
            var list = _db.Goods.Join(_db.Categories, x => x.CateId, y => y.Id,
                 //4、构造一个新的查询结果 把两个表的字段结合 
                 (x, y) => new
                 {
                     x.Id,
                     x.Name,
                     y.CateName
                 }).ToList();

            return new ObjectResult(list);
        }
        //在Join控制器添加JoinGoods方法名，查询分类名称为“数码”的商品数据
        public IActionResult JoinGoods()
        {
            var list = _db.Goods.Join(_db.Categories, x => x.CateId, y => y.Id,
                (x, y) => new
                {
                    x.Id,
                    x.Name,
                    y.CateName
                }).Where(x=>x.CateName == "数码").ToList();
            return new ObjectResult(list);
        }
    }
}
